package com.qws.xprinter.flutter_xprinter.device

import android.os.Handler
import android.os.Looper
import android.util.Log
import com.gprinter.bean.PrinterDevices
import com.gprinter.utils.CallbackListener
import com.gprinter.utils.Command
import com.gprinter.utils.ConnMethod
import com.qws.xprinter.flutter_xprinter.App
import com.qws.xprinter.flutter_xprinter.bean.ConnType
import com.qws.xprinter.flutter_xprinter.queue.PrintTaskQueue
import com.qws.xprinter.flutter_xprinter.utils.Utils
import net.posprinter.POSConnect

class GPrinter(private val connType: Int, private val address: String) : QwsPrinter,
    CallbackListener {

    private var taskQueue: PrintTaskQueue = PrintTaskQueue()
    private val printerManager = GPrinterManager()
    private val handler: Handler = Handler(Looper.getMainLooper())
    private val closeRunnable = Runnable {
        taskQueue.pause()
        disconnect()
    }

    init {
        taskQueue.setPrintQueueListener(object : PrintTaskQueue.PrintQueueListener {
            override fun onQueueEmpty() {
                handler.postDelayed(closeRunnable, 1000 * 60 * 3)
            }
        })
    }

    override fun connect() {
        val build = PrinterDevices.Build()
            .setContext(App.get())
            .setCallbackListener(this)
        var device: PrinterDevices? = null
        when (connType) {
            ConnType.USB.ordinal -> {
                device = build.setConnMethod(ConnMethod.USB)
                    .setCommand(Command.ESC)
                    .setUsbDevice(Utils.getUsbDeviceFromName(App.get(), address))
                    .build()
            }

            ConnType.BLUETOOTH.ordinal -> {
                device = build.setConnMethod(ConnMethod.BLUETOOTH)
                    .setCommand(Command.ESC)
                    .setMacAddress(address)
                    .build()
            }

            ConnType.NET.ordinal -> {
                device = build.setConnMethod(ConnMethod.WIFI)
                    .setIp(address)
                    .setPort(9100)
                    .build()
            }
        }
        printerManager.connect(device)
    }

    override fun disconnect() {
        printerManager.close()
    }

    override fun sendPrintTask(bytes: List<Int>) {
        handler.removeCallbacks(closeRunnable)
        taskQueue.addTask {
            try {
                // 确保连接状态正常再发送数据
                if (printerManager.connectState) {
                    printerManager.sendDataToPrinter(bytes.toTypedArray().toByteArray())
                    Log.i("GPrinter", "打印数据发送成功")
                } else {
                    taskQueue.pause()
                    taskQueue.addTask{printerManager.sendDataToPrinter(bytes.toTypedArray().toByteArray())}
                    connect()
                    Log.e("GPrinter", "打印失败：连接已断开")
                }
            } catch (e: Exception) {
                taskQueue.pause()
                taskQueue.addTask{printerManager.sendDataToPrinter(bytes.toTypedArray().toByteArray())}
                Log.e("GPrinter", "打印异常: ${e.message}")
            }
        }
        
        // 检查连接状态并处理
        if (printerManager.connectState) {
            Log.i("GPrinter", "打印机已连接，继续执行队列")
            taskQueue.resume()
        } else {
            Log.i("GPrinter", "打印机未连接，尝试重新连接")
            connect()
        }
        Log.i("GPrinter", "sendPrintTask添加完成")
    }

    override fun onConnecting() {
    }

    override fun onCheckCommand() {
    }

    override fun onSuccess(printerDevices: PrinterDevices?) {
        App.get().channel?.invokeMethod(
            "connect",
            mapOf("code" to POSConnect.CONNECT_SUCCESS, "address" to address)
        )
        Log.i("GPrinter", "onSuccess")
        taskQueue.resume()
    }

    override fun onReceive(data: ByteArray?) {
        Log.i("GPrinter", "onReceive ${data?.size}")
    }

    override fun onFailure() {
        Log.i("GPrinter", "onFailure")
//        disconnect()
//        handler.postDelayed({
//            connect()
//        }, 1000)
        App.get().channel?.invokeMethod(
            "connect",
            mapOf("code" to POSConnect.CONNECT_FAIL, "address" to address)
        )
        taskQueue.pause()
    }

    override fun onDisconnect() {
        Log.i("GPrinter", "onDisconnect")
        App.get().channel?.invokeMethod(
            "connect",
            mapOf("code" to POSConnect.CONNECT_FAIL, "address" to address)
        )
        taskQueue.pause()
    }

}